// 导入关联模型（Order/OrderItem/User/Product）、Sequelize操作符、错误处理、事务
const { Order, OrderItem, User, Product } = require("../models");
const { Op, Transaction } = require("sequelize");
const createError = require("http-errors");

/**
 * 订单服务类：封装订单全生命周期业务逻辑
 */
class OrderService {
  /**
   * 获取所有订单（分页+筛选+联表用户）
   * @param {number} page - 页码
   * @param {number} limit - 每页条数
   * @param {Object} filters - 筛选条件（userId/status/paymentStatus/startTime/endTime）
   * @returns {Object} { orders: 订单列表, pagination: 分页信息 }
   */
  async findAllOrders(page = 1, limit = 10, filters = {}) {
    try {
      const offset = (page - 1) * limit;
      const whereClause = {};

      // 1. 动态构建筛选条件
      // 按用户ID筛选
      if (filters.userId) {
        whereClause.userId = filters.userId;
      }
      // 按订单状态筛选（枚举值：pending/confirmed/processing/shipped/delivered/cancelled/refunded）
      if (filters.status) {
        whereClause.status = filters.status;
      }
      // 按支付状态筛选（枚举值：pending/paid/failed/refunded）
      if (filters.paymentStatus) {
        whereClause.paymentStatus = filters.paymentStatus;
      }
      // 按时间范围筛选（创建时间）
      if (filters.startTime || filters.endTime) {
        whereClause.createdAt = {};
        if (filters.startTime) {
          whereClause.createdAt[Op.gte] = new Date(
            `${filters.startTime} 00:00:00`
          ); // 大于等于开始时间
        }
        if (filters.endTime) {
          whereClause.createdAt[Op.lte] = new Date(
            `${filters.endTime} 23:59:59`
          ); // 小于等于结束时间
        }
      }

      // 2. 执行分页查询（联表用户，排除用户密码）
      const { count, rows } = await Order.findAndCountAll({
        where: whereClause,
        include: [
          {
            model: User,
            attributes: { exclude: ["password"] }, // 安全：不返回用户密码
            as: "user", // 关联别名（需在模型中定义associate）
          },
        ],
        order: [["createdAt", "DESC"]], // 按创建时间倒序（最新订单在前）
        limit: parseInt(limit),
        offset: offset,
      });

      return {
        orders: rows,
        pagination: {
          page: parseInt(page),
          limit: parseInt(limit),
          total: count,
          pages: Math.ceil(count / limit),
        },
      };
    } catch (error) {
      throw new Error(`获取订单列表失败: ${error.message}`);
    }
  }

  /**
   * 获取单个订单详情（联表：用户+订单项+产品）
   * @param {number/string} id - 订单ID
   * @returns {Object} 订单详情（含用户、订单项+产品信息）
   */
  async findOrderById(id) {
    try {
      const order = await Order.findByPk(id, {
        include: [
          // 1. 关联用户（排除密码）
          {
            model: User,
            attributes: { exclude: ["password"] },
            as: "user",
          },
          // 2. 关联订单项（嵌套关联产品）
          {
            model: OrderItem,
            as: "orderItems",
            include: [
              {
                model: Product,
                as: "product",
                attributes: [
                  "id",
                  "name",
                  "image",
                  "price",
                  "originalPrice",
                  "status",
                ], // 仅返回产品关键信息，避免冗余
              },
            ],
          },
        ],
      });

      // 订单不存在返回404
      if (!order) {
        throw createError(404, "订单不存在");
      }

      return order;
    } catch (error) {
      if (error.status === 404) throw error;
      throw new Error(`获取订单详情失败: ${error.message}`);
    }
  }

  /**
   * 创建订单（事务保证：订单+订单项原子性，避免数据不一致）
   * @param {Object} orderData - 订单数据：{ userId, paymentMethod, shippingAddress, items: [] }
   * items格式：[{ productId, quantity, price }, ...]
   * @returns {Object} 新创建的订单（含订单项）
   */
  async createOrder(orderData) {
    // 1. 校验必要参数
    const { userId, paymentMethod, shippingAddress, items } = orderData;
    if (!userId || !paymentMethod || !shippingAddress || !items?.length) {
      throw createError(
        400,
        "缺少必要参数：userId/paymentMethod/shippingAddress/items"
      );
    }

    // 2. 开启Sequelize事务（确保订单和订单项要么同时成功，要么同时失败）
    const transaction = await Transaction.create();

    try {
      // 3. 校验用户是否存在
      const user = await User.findByPk(userId);
      if (!user) {
        throw createError(404, "关联的用户不存在");
      }

      // 4. 校验订单项中的产品是否存在、库存是否充足，并计算订单总金额
      let totalAmount = 0;
      const validItems = [];

      for (const item of items) {
        const { productId, quantity, price } = item;
        // 校验产品存在性
        const product = await Product.findByPk(productId);
        if (!product) {
          throw createError(404, `订单项中产品不存在：productId=${productId}`);
        }
        // 校验产品状态（仅active状态可购买）
        if (product.status !== "active") {
          throw createError(
            400,
            `产品不可购买：${product.name}（状态：${product.status}）`
          );
        }
        // 校验库存
        if (product.stock < quantity) {
          throw createError(
            400,
            `产品库存不足：${product.name}（库存：${product.stock}，需求：${quantity}）`
          );
        }
        // 计算订单项小计，并累加订单总金额
        const itemTotal = price * quantity;
        totalAmount += itemTotal;
        // 收集合法订单项（用于后续创建）
        validItems.push({
          productId,
          quantity,
          price,
          total: itemTotal,
          createdAt: new Date(),
          updatedAt: new Date(),
        });
      }

      // 5. 生成唯一订单号（格式：ORD+年月日+6位随机数，如 ORD20240520123456）
      const orderNumber = `ORD${new Date().format("yyyyMMdd")}${Math.floor(
        Math.random() * 1000000
      )
        .toString()
        .padStart(6, "0")}`;

      // 6. 创建订单记录
      const order = await Order.create(
        {
          userId,
          orderNumber,
          totalAmount, // 订单总金额（订单项小计总和）
          status: "pending", // 默认初始状态：待确认
          shippingAddress, // JSON格式：{ recipient, phone, province, city, district, detail }
          paymentMethod, // 支付方式：credit_card/paypal/bank_transfer/cod
          paymentStatus: "pending", // 默认支付状态：待支付
          createdAt: new Date(),
          updatedAt: new Date(),
        },
        { transaction } // 绑定事务
      );

      // 7. 批量创建订单项（关联当前订单ID）
      const orderItems = validItems.map((item) => ({
        ...item,
        orderId: order.id, // 关联订单ID
      }));
      await OrderItem.bulkCreate(orderItems, { transaction });

      // 8. 扣减产品库存（下单成功后减少对应产品库存）
      for (const item of validItems) {
        await Product.increment(
          { stock: -item.quantity }, // 库存减少quantity
          {
            where: { id: item.productId },
            transaction,
          }
        );
      }

      // 9. 提交事务
      await transaction.commit();

      // 10. 返回订单详情（含订单项）
      return this.findOrderById(order.id);
    } catch (error) {
      // 事务回滚：发生错误时撤销所有操作
      await transaction.rollback();
      if (error.status) throw error; // 若为HTTP错误（400/404）直接抛出
      throw new Error(`创建订单失败: ${error.message}`);
    }
  }

  /**
   * 更新订单信息（仅允许更新非关键字段：状态、收货地址、支付状态）
   * @param {number/string} id - 订单ID
   * @param {Object} updateData - 待更新字段（status/paymentStatus/shippingAddress）
   * @returns {Object} 更新后的订单
   */
  async updateOrder(id, updateData) {
    try {
      // 1. 校验订单是否存在
      const order = await Order.findByPk(id);
      if (!order) {
        throw createError(404, "订单不存在");
      }

      // 2. 限制可更新字段（禁止修改订单号、总金额、用户ID等关键信息）
      const allowedFields = ["status", "paymentStatus", "shippingAddress"];
      const updateFields = {};
      for (const field of allowedFields) {
        if (updateData[field] !== undefined) {
          updateFields[field] = updateData[field];
        }
      }

      // 3. 若更新状态为“取消”，需恢复产品库存（事务处理）
      if (updateFields.status === "cancelled" && order.status !== "cancelled") {
        const transaction = await Transaction.create();
        try {
          // 3.1 获取订单关联的订单项
          const orderItems = await OrderItem.findAll({
            where: { orderId: id },
            transaction,
          });

          // 3.2 恢复每个产品的库存
          for (const item of orderItems) {
            await Product.increment(
              { stock: item.quantity }, // 库存增加quantity
              {
                where: { id: item.productId },
                transaction,
              }
            );
          }

          // 3.3 更新订单状态和支付状态（取消订单默认支付状态为refunded）
          updateFields.paymentStatus = "refunded";
          await order.update(
            { ...updateFields, updatedAt: new Date() },
            { transaction }
          );

          await transaction.commit();
        } catch (err) {
          await transaction.rollback();
          throw new Error(`取消订单失败: ${err.message}`);
        }
      } else {
        // 4. 普通更新（非取消状态）
        await order.update({ ...updateFields, updatedAt: new Date() });
      }

      // 5. 返回更新后的订单详情
      return this.findOrderById(id);
    } catch (error) {
      if (error.status) throw error;
      throw new Error(`更新订单失败: ${error.message}`);
    }
  }

  /**
   * 删除订单（级联删除订单项，恢复产品库存）
   * @param {number/string} id - 订单ID
   * @returns {Object} { message: 提示信息 }
   */
  async deleteOrder(id) {
    const transaction = await Transaction.create();
    try {
      // 1. 校验订单是否存在
      const order = await Order.findByPk(id, { transaction });
      if (!order) {
        throw createError(404, "订单不存在");
      }

      // 2. 获取订单关联的订单项
      const orderItems = await OrderItem.findAll({
        where: { orderId: id },
        transaction,
      });

      // 3. 恢复产品库存（仅非取消状态的订单需要恢复）
      if (order.status !== "cancelled") {
        for (const item of orderItems) {
          await Product.increment(
            { stock: item.quantity },
            { where: { id: item.productId }, transaction }
          );
        }
      }

      // 4. 级联删除订单项
      await OrderItem.destroy({
        where: { orderId: id },
        transaction,
      });

      // 5. 删除订单
      await Order.destroy({
        where: { id },
        transaction,
      });

      await transaction.commit();
      return { message: "订单删除成功" };
    } catch (error) {
      await transaction.rollback();
      if (error.status) throw error;
      throw new Error(`删除订单失败: ${error.message}`);
    }
  }

  /**
   * 根据用户ID查询订单数量
   * @param {number} userId - 用户ID
   * @returns {number} 订单数量
   */
  async getUserOrderCount(userId) {
    try {
      // 先验证用户是否存在（可选，根据业务需求决定是否需要）
      const user = await User.findByPk(userId);
      if (!user) {
        throw createError(404, `用户不存在（ID：${userId}）`);
      }

      // 统计该用户的订单数量（直接查询Order表，性能最优）
      const orderCount = await Order.count({
        where: { userId: userId }, // 按用户ID筛选
      });

      return orderCount;
    } catch (error) {
      if (error.status) throw error;
      throw new Error(`查询用户订单数量失败: ${error.message}`);
    }
  }
}

// 导出单例服务实例
module.exports = new OrderService();
